package com.abewy.android.apps.klyph.core.request; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.os.Bundle; import android.util.JsonReader; import android.util.Log; import com.abewy.android.apps.klyph.core.BaseApplication; import com.abewy.android.apps.klyph.core.KlyphFlags; import com.abewy.android.apps.klyph.core.KlyphLocale; import com.abewy.android.apps.klyph.core.KlyphSession; import com.abewy.android.apps.klyph.core.graph.GraphObject; import com.abewy.android.apps.klyph.core.request.DeserializeTask.DeserializeCallback; import com.facebook.FacebookRequestError; import com.facebook.HttpMethod; import com.facebook.Session; public abstract class BaseAsyncRequest implements DeserializeCallback { private com.facebook.Request request; public interface Callback { void onComplete(Response response); } private int query; private String id; private String offset; private Bundle params; private Callback callBack; private RequestQuery subQuery; private List<GraphObject> previousResults; private String afterCursor; private String beforeCursor; private String pagingBefore; private String pagingNext; public BaseAsyncRequest(int query, String id, String offset, Callback callBack) { this.query = query; this.id = id; this.offset = offset; this.callBack = callBack; subQuery = getSubQuery(query); } public BaseAsyncRequest(int query, String id, Bundle params, Callback callBack) { this.query = query; this.id = id; this.params = params; this.callBack = callBack; subQuery = getSubQuery(query); } protected int getQuery() { return query; } protected String getId() { return id; } protected String getOffset() { return offset; } public void cancel() { if (request != null) { request.setCallback(null); request = null; } } public void execute() { execute(subQuery); } private void execute(RequestQuery query) { if (KlyphFlags.LOG_REQUEST_EXEC) { Log.d("AsyncRequest " + query.toString(), "id = " + id + ", offset = " + offset); } if (KlyphSession.getSessionUser() == null) return; com.facebook.Request r = getRequest(); startTime = new Date().getTime(); com.facebook.Request.executeBatchAsync(r); } public static void executeBatch(List<? extends BaseAsyncRequest> requests) { List<com.facebook.Request> fbRequests = new ArrayList<com.facebook.Request>(); for (BaseAsyncRequest asyncRequest : requests) { fbRequests.add(asyncRequest.getRequest()); } com.facebook.Request.executeBatchAsync(fbRequests); } protected com.facebook.Request getRequest() { String path = (subQuery.isFQL() == true) ? "/fql" : subQuery.getQuery(id, offset); Bundle params = new Bundle(); params.putString("locale", KlyphLocale.getFbLocale()); params.putString("date_format", "U"); // Get dates in unix timestamp format if (subQuery.getHttpMethod() == HttpMethod.GET) { if (subQuery.isFQL() == true) { String q = subQuery.isNextQuery() == false ? subQuery.getQuery(id, offset) : subQuery.getQuery(previousResults, id, offset); params.putString("q", q); } } else { if (this.params != null) { for (String key : this.params.keySet()) { params.putString(key, this.params.getString(key)); } } } Bundle queryParams = subQuery.getParams(); if (queryParams != null) { for (String key : queryParams.keySet()) { params.putString(key, queryParams.getString(key)); } } if (Session.getActiveSession() == null) Session.openActiveSessionFromCache(BaseApplication.getInstance()); request = new com.facebook.Request(Session.getActiveSession(), path, params, subQuery.getHttpMethod(), new com.facebook.Request.Callback() { public void onCompleted(com.facebook.Response response) { handleResponse(response); } }); return request; } private long startTime; protected void handleResponse(com.facebook.Response response) { if (KlyphFlags.LOG_REQUEST_PERFORMANCE) { Log.d("TIME " + query, "requestTime = " + (new Date().getTime() - startTime)); startTime = new Date().getTime(); } /* * Log.d("BaseAsyncRequest", "response " + response); * Log.d("BaseAsyncRequest", "response error" + response.getError()); * Log.d("BaseAsyncRequest", "response graph" + response.getGraphObject()); */ if ((response.getError() == null || response.getError().getErrorCode() == -1) && (response.getGraphObject() != null || response.getGraphObjectList() != null)) { // if (KlyphFlags.LOG_REQUEST_RESULT == true) // longInfo(jsonResponse.toString()); try { if (subQuery.isFQL()) { JSONObject jsonResponse = response.getGraphObject().getInnerJSONObject(); if (subQuery.returnId()) { String id = (String) response.getGraphObject().getProperty("id"); doCallBack(id); } else if (!subQuery.getHttpMethod().equals(HttpMethod.GET)) { doCallBack(new ArrayList<GraphObject>()); } else if (subQuery.isMultiQuery()) { JSONArray data = (JSONArray) jsonResponse.getJSONArray("data"); new DeserializeTask(subQuery, previousResults, this).execute(data); } else { JSONArray data = (JSONArray) jsonResponse.getJSONArray("data"); new DeserializeTask2(subQuery, previousResults, this).execute(data); } } else { if (subQuery.returnId()) { String id = (String) response.getGraphObject().getProperty("id"); doCallBack(id); } else if (!subQuery.isMultiQuery()) { JSONObject jsonResponse = response.getGraphObject().getInnerJSONObject(); doCallBack(subQuery.handleResult(jsonResponse)); } /* * else * { * JSONArray data = response.getGraphObjectList().getInnerJSONArray(); * new DeserializeTask3(subQuery, previousResults, this).execute(data); * } */ else { JSONObject jsonResponse = response.getGraphObject().getInnerJSONObject(); JSONObject paging = jsonResponse.optJSONObject("paging"); if (paging != null) { JSONObject cursors = paging.optJSONObject("cursors"); if (cursors != null) { afterCursor = cursors.optString("after"); beforeCursor = cursors.optString("before"); } pagingBefore = paging.optString("before"); pagingNext = paging.optString("next"); } JSONArray data = (JSONArray) jsonResponse.getJSONArray("data"); new DeserializeTask2(subQuery, previousResults, this).execute(data); } } } catch (JSONException e) { RequestError error = new RequestError(999, "JSONException", e.getMessage()); doCallBack(error); } } else { longInfo("Error " + response.getError()); FacebookRequestError fbError = response.getError(); if (KlyphFlags.ENABLE_BUG_REPORT) { /* * if (query == Query.POST_LIKE || query == Query.POST_UNLIKE || query == Query.POST_COMMENT * || query == Query.NOTIFICATIONS) * { * ACRA.getErrorReporter().handleSilentException(fbError.getException()); * } */ } RequestError error = new RequestError(fbError.getErrorCode(), fbError.getErrorType(), fbError.getErrorMessage()); doCallBack(error); } } @Override public void onDeserializeComplete(List<GraphObject> result) { doCallBack(result); } @Override public void onDeserializeComplete(RequestError error) { doCallBack(error); } protected void doCallBack(RequestError error) { doCallBack(error, null, null); } protected void doCallBack(List<GraphObject> objects) { if (subQuery.getNextQuery() == null) { doCallBack(null, null, objects); } else { previousResults = objects; subQuery = subQuery.getNextQuery(); execute(subQuery); } } protected void doCallBack(String id) { if (KlyphFlags.LOG_REQUEST_PERFORMANCE) Log.d("TIME " + query, "deserializeTime = " + (new Date().getTime() - startTime)); if (callBack != null) { final Response response = new Response(id); callBack.onComplete(response); /* * Runnable runnable = new Runnable() { * public void run() * { * callBack.onComplete(response); * } * }; * * runnable.run(); */ } } protected void doCallBack(RequestError error, GraphObject object, List<GraphObject> objects) { if (KlyphFlags.LOG_REQUEST_PERFORMANCE) Log.d("TIME " + query, "deserializeTime = " + (new Date().getTime() - startTime)); if (callBack != null) { final Response response = new Response(error, object, objects); callBack.onComplete(response); /* * Runnable runnable = new Runnable() { * public void run() * { * callBack.onComplete(response); * } * }; * * runnable.run(); */ } } protected abstract RequestQuery getSubQuery(int query); protected void longInfo(String str) { if (str.length() > 4000) { Log.d("AsyncRequest", str.substring(0, 4000)); longInfo(str.substring(4000)); } else Log.d("AsyncRequest", str); } public boolean hasMoreData() { return subQuery.hasMoreData(); } public String getAfterCursor() { return afterCursor; } public String getBeforeCursor() { return beforeCursor; } public String getPagingBefore() { return pagingBefore; } public String getPagingNext() { return pagingNext; } }